package spindles.api.domain;

import static javax.measure.units.SI.MILLI;
import static javax.measure.units.SI.SECOND;

import java.util.Date;

import javax.measure.quantities.Duration;
import javax.measure.quantities.Scalar;
import javax.measure.units.SI;

import org.apache.commons.lang.time.DateUtils;

import com.sleepycat.persist.model.Persistent;

@Persistent
public class Spindle extends Interval{
	public static final int VD_SPINDLE = 1;
	public static final int SPINDLE_INDICATION = 2;
	
	private ISI isi;
	
	private double relativeStartTime;
	
	private double relativeEndTime;
	
	public static final Scalar<Duration> MIN_INTERSECT_DURATION =
		new Scalar<Duration>(0.3d, SI.SECOND);
	
	/**
	 * 
	 */
	private static transient final long serialVersionUID = 1551857977688471517L;

	public Spindle(){
		super();
	}
	
	public Spindle(Date from, Date to){
		super(from, to);
	}
	
	
	/**
	 * For a VDS and a SI to coincide:
	 * <ul>
	 * 	<li>VDS must be within SI or</li>
	 *  <li>VDS must intersect with SI for at least MIN_INTERSECT_DURATION
	 *  seconds, if VDS duration is longer or equal to MIN_INTERSECT_DURATION
	 *  </li>
	 *    
	 * </ul>
	 * 
	 * @param si
	 * @return
	 */
	public boolean coincide(Interval si){
		Scalar<Duration> minIntersectDuration;
		if (this.duration().compareTo(MIN_INTERSECT_DURATION) >= 0) {
			minIntersectDuration = new Scalar<Duration>(0.1d, SI.SECOND);
		} else {
			minIntersectDuration = new Scalar<Duration>(this.duration()
					.doubleValue()
					* (1 / 3), this.duration().getUnit());
		}		
		
		int minDurMillis = (int)minIntersectDuration.longValue(MILLI(SECOND));
		
		Date lastTimePoint = DateUtils.addMilliseconds(si.getStart(), minDurMillis);		
		if(this.contains(si.getStart()) && this.contains(lastTimePoint) && si.contains(lastTimePoint)){
			return true;
		}
		
		Date firstTimePoint = DateUtils.addMilliseconds(si.getEnd(), -minDurMillis);
		if(this.contains(si.getEnd()) && this.contains(firstTimePoint) && si.contains(firstTimePoint)){
			return true;
		}
		
		if(si.contains(this)){
			return true;
		}
		
		return false;
	}

	public ISI getIsi() {
		return isi;
	}

	public void setIsi(ISI isi) {
		this.isi = isi;
	}

	public double getRelativeEndTime() {
		return relativeEndTime;
	}

	public void setRelativeEndTime(double relativeEndTime) {
		this.relativeEndTime = relativeEndTime;
	}

	public double getRelativeStartTime() {
		return relativeStartTime;
	}

	public void setRelativeStartTime(double relativeStartTime) {
		this.relativeStartTime = relativeStartTime;
	}
}
